/** 
 * ================================================================================
 * 		Project		: Kompas Bola
 * 		File		: AbstractTabStackNavigation.java
 * 		Description	: Tab UI
 * 		Called		: KlasemenActivity.java
 * ================================================================================
 * */
package com.kompas.bola.application.ui;

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import android.annotation.SuppressLint;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.kompas.bola.application.R;

public abstract class AbstractTabStackNavigation extends
		SherlockFragmentActivity {
	/** =========================================================================== */

	public static final String LOGTAG 				= AbstractTabStackNavigation.class
													.getSimpleName();

	boolean changeOfStackAllowedForTabListener 		= true;
	WeakHashMap<Fragment, Boolean> fragmentWasAdded = new WeakHashMap<Fragment, Boolean>();

	@SuppressLint("UseSparseArrays")
	private final Map<Integer, TabInfo> tabMap 		= new HashMap<Integer, TabInfo>();
	/** =========================================================================== */
	public void addTab(final ActionBar.Tab tab, final Fragment fragment) {
		final Integer tag 							= tabMap.size();
		final TabInfo tabInfo 						= new TabInfo(this);
		tabInfo.tag 								= tag;
		tabInfo.tab 								= tab;
		tabInfo.stack.push(fragment);
		tab.setTabListener(new TabListener(
				getSupportFragmentManager(), tabInfo));
		tab.setTag(tag);
		tabMap.put(tag, tabInfo);
		getSupportActionBar().addTab(tab);
	}
	/** =========================================================================== */
	protected abstract void createTabs();
	/** =========================================================================== */
	public TabInfo getCurrentTabInfo() {
		final int index 							= getSupportActionBar().getSelectedNavigationIndex();
		final TabInfo tabInfo 						= tabMap.get(index);
		return tabInfo;
	}
	/** =========================================================================== */
	@Override
	public void onConfigurationChanged(final Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		setContentView(R.layout.tab_navigation);
	}
	/** =========================================================================== */
	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
		setContentView(R.layout.tab_navigation);
		setSupportProgressBarIndeterminateVisibility(false);
		if (savedInstanceState == null) {
			createTabs();
		}
	}
	/** =========================================================================== */
	@Override
	public boolean onOptionsItemSelected(final MenuItem item) {
		if (item.getItemId() == android.R.id.home) {}
		return super.onOptionsItemSelected(item);
	}
	/** =========================================================================== */
	public void popFragment() {
		Log.d(LOGTAG, "popFragment()");
		final TabInfo tabInfo = getCurrentTabInfo();
		if (tabInfo.stack.size() <= 1) {
			Log.d(LOGTAG, "popFragment() - nothing to pop...");
			return;
		}
		final FragmentManager fragmentManager 		= getSupportFragmentManager();
		final FragmentTransaction ft 				= fragmentManager.beginTransaction();
		tabInfo.detachFragment(ft, tabInfo.stack.pop());
		tabInfo.attachFragment(ft, tabInfo.stack.peek());
		ft.commit();
	}
	/** =========================================================================== */
	public void pushFragment(final TabInfo tabInfo, final Fragment fragment) {
		pushOrReplaceFragment(tabInfo, fragment, false, true);
	}
	/** =========================================================================== */
	public void pushOrReplaceFragment(final TabInfo tabInfo,
			final Fragment fragment, final boolean replaceInsteadOfPush,
			final boolean pushEvenIfSameClassAsTopFragment) {
		
		final boolean onWrongTab 					= getCurrentTabInfo() != tabInfo;
		final boolean newFragmentIsOfSameClassAsOldFragment = tabInfo.stack
				.size() > 0
				&& tabInfo.stack.peek().getClass().equals(fragment.getClass());
				
		final boolean justReplacePreviousFragment 	= replaceInsteadOfPush
				|| (newFragmentIsOfSameClassAsOldFragment && !pushEvenIfSameClassAsTopFragment);
		
		final FragmentManager fragmentManager 		= getSupportFragmentManager();
		final FragmentTransaction ft 				= fragmentManager.beginTransaction();
		
		tabInfo.detachFragment(ft, tabInfo.stack.peek());
		if (justReplacePreviousFragment) {
			Log.d(LOGTAG,
					"replace previous fragment because it's of same class");
			tabInfo.stack.pop();
		}
		
		tabInfo.stack.push(fragment);
		tabInfo.attachFragment(ft, fragment);
		ft.commit();
		
		if (onWrongTab) {
			Log.d(LOGTAG, "on wrong tab, select tab " + tabInfo.tag);
			changeOfStackAllowedForTabListener 		= false;
			try {
				getSupportActionBar().setSelectedNavigationItem(tabInfo.tag);
			} finally {
				changeOfStackAllowedForTabListener 	= true;
			}
		}
		setUpButtonDependingStack();
	}
	/** =========================================================================== */
	public void replaceFragment(final TabInfo tabInfo, final Fragment fragment) {
		pushOrReplaceFragment(tabInfo, fragment, true, true);
	}
	/** =========================================================================== */
	protected void setUpButtonDependingStack() {
		final boolean upButtonEnabled = getCurrentTabInfo().stack.size() > 1;
		Log.d(LOGTAG, "setUpButton(" + upButtonEnabled + ")");
		getSupportActionBar().setDisplayHomeAsUpEnabled(upButtonEnabled);
		getSupportActionBar().setHomeButtonEnabled(upButtonEnabled);
	}
	/** =========================================================================== */
}
